#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import aimsedit
import qrc_resources

__version__ = "1.0.0"


class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.mdi = QWorkspace()
        self.setCentralWidget(self.mdi)

        # создадим действия:
        self.fileNewAction       = self.createAction("&New", self.fileNew, QKeySequence.New, "filenew", "Create a aims file")
        self.fileOpenAction      = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing aims file")
        self.fileSaveAction      = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save aims")
        self.fileSaveAsAction    = self.createAction("Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save aims using a new filename")
        self.fileSaveAllAction   = self.createAction("Save A&ll", self.fileSaveAll, "filesave", tip="Save all the files")
        self.fileQuitAction      = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application")
        self.fileExportPDFAction = self.createAction("Export to &PDF", self.fileExport2Pdf, icon="pdf", tip="Save your aims as PDF file")

        self.editCopyAction  = self.createAction("&Copy", self.editCopy, QKeySequence.Copy, "editcopy", "Copy aim to the clipboard")
        self.editCutAction   = self.createAction("Cu&t", self.editCut, QKeySequence.Cut, "editcut", "Cut aim to the clipboard")
        self.editPasteAction = self.createAction("&Paste", self.editPaste, QKeySequence.Paste, "editpaste", "Paste in the clipboard's aim")

        self.windowNextAction         = self.createAction("&Next", self.mdi.activateNextWindow, QKeySequence.NextChild)
        self.windowPrevAction         = self.createAction("&Previous", self.mdi.activatePreviousWindow, QKeySequence.PreviousChild)
        self.windowCascadeAction      = self.createAction("Casca&de", self.mdi.cascade)
        self.windowTileAction         = self.createAction("&Tile", self.mdi.tile)
        self.windowRestoreAction      = self.createAction("&Restore All", self.windowRestoreAll)
        self.windowMinimizeAction     = self.createAction("&Iconize All", self.windowMinimizeAll)
        self.windowArrangeIconsAction = self.createAction("&Arrange Icons", self.mdi.arrangeIcons)
        self.windowCloseAction        = self.createAction("&Close", self.mdi.closeActiveWindow, QKeySequence.Close)

        self.windowMapper = QSignalMapper(self)
        self.connect(self.windowMapper, SIGNAL("mapped(QWidget*)"), self.mdi, SLOT("setActiveWindow(QWidget*)"))

        # разместим действия по соответствующим пунктам меню:
        fileMenu = self.menuBar().addMenu("&File")
        self.addActions(fileMenu, (self.fileNewAction
                                 , self.fileOpenAction
                                 , self.fileSaveAction
                                 , self.fileSaveAsAction
                                 , self.fileSaveAllAction
                                 , None
                                 , self.fileExportPDFAction
                                 , None
                                 , self.fileQuitAction))

        editMenu = self.menuBar().addMenu("&Edit")
        self.addActions(editMenu, (self.editCopyAction
                                 , self.editCutAction
                                 , self.editPasteAction))

        self.windowMenu = self.menuBar().addMenu("&Window")
        self.connect(self.windowMenu, SIGNAL("aboutToShow()"),
                     self.updateWindowMenu)

        fileToolbar = self.addToolBar("File")
        fileToolbar.setObjectName("FileToolbar")
        self.addActions(fileToolbar, (self.fileNewAction
                                    , self.fileOpenAction
                                    , self.fileSaveAction
                                    , self.fileExportPDFAction))

        editToolbar = self.addToolBar("Edit")
        editToolbar.setObjectName("EditToolbar")
        self.addActions(editToolbar, (self.editCopyAction
                                    , self.editCutAction
                                    , self.editPasteAction))

        QApplication.clipboard().setText("")
        self.setActionsEnabled()

        settings = QSettings()
        size     = settings.value("MainWindow/Size", QVariant(QSize(600, 500))).toSize()
        self.resize(size)
        position = settings.value("MainWindow/Position", QVariant(QPoint(0, 0))).toPoint()
        self.move(position)
        self.restoreState(settings.value("MainWindow/State").toByteArray())

        status = self.statusBar()
        status.setSizeGripEnabled(False)
        status.showMessage("Ready", 5000)

        self.updateWindowMenu()
        self.setWindowTitle("Aims Editor")
        QTimer.singleShot(0, self.loadFiles)


    def createAction(self, text, slot=None, shortcut=None, icon=None,
                     tip=None, checkable=False, signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action


    def addActions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)


    def closeEvent(self, event):
        toRestoreModified = []
        for aimsEdit in self.mdi.windowList():
            if aimsEdit.isModified():
                desigion = QMessageBox.warning(self, "Aims Editor -- do you want to save changes?",
                    "Some changes in %s unsaved. Save them?" % aimsEdit.filename,
                    QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
                if desigion == QMessageBox.Yes:
                    aimsEdit.save()
                elif desigion == QMessageBox.Cancel:
                    event.ignore()
                    for edit in toRestoreModified:
                        edit.setModified(True)
                    return
                else:
                    aimsEdit.setModified(False)
                    toRestoreModified.append(aimsEdit)  
                
        settings = QSettings()
        settings.setValue("MainWindow/Size", QVariant(self.size()))
        settings.setValue("MainWindow/Position",
                QVariant(self.pos()))
        settings.setValue("MainWindow/State",
                QVariant(self.saveState()))
        files = QStringList()
        for aimsEdit in self.mdi.windowList():
            if not aimsEdit.filename.startsWith("Unnamed"):
                files.append(aimsEdit.filename)
        settings.setValue("CurrentFiles", QVariant(files))
        self.mdi.closeAllWindows()


    def loadFiles(self):
        if len(sys.argv) > 1:
            for filename in sys.argv[1:31]: # Load at most 30 files
                filename = QString(filename)
                if QFileInfo(filename).isFile():
                    self.loadFile(filename)
                    QApplication.processEvents()
        else:
            settings = QSettings()
            files = settings.value("CurrentFiles").toStringList()
            for filename in files:
                filename = QString(filename)
                if QFile.exists(filename):
                    self.loadFile(filename)
                    QApplication.processEvents()


    def fileNew(self):
        aimsEdit = aimsedit.AimsEdit()
        self.mdi.addWindow(aimsEdit)
        self.connect(aimsEdit, SIGNAL("currentAimChanged"), self.setActionsEnabled)
        aimsEdit.show()
        self.setActionsEnabled()


    def fileOpen(self):
        filename = QFileDialog.getOpenFileName(self,
                            "Aims Editor -- Open File")
        if not filename.isEmpty():
            for aimsEdit in self.mdi.windowList():
                if aimsEdit.filename == filename:
                    self.mdi.setActiveWindow(aimsEdit)
                    break
            else:
                self.loadFile(filename)
        self.setActionsEnabled()


    def loadFile(self, filename):
        try:
            aimsEdit = aimsedit.AimsEdit(filename)
        except (IOError, OSError), e:
            QMessageBox.warning(self, "Aims Editor -- Load Error",
                    "Failed to load %s: %s" % (filename, e))
            aimsEdit.close()
            del aimsEdit
        else:
            self.mdi.addWindow(aimsEdit)
            self.connect(aimsEdit, SIGNAL("currentAimChanged"), self.setActionsEnabled)
            aimsEdit.show()


    def fileSave(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None or not isinstance(aimsEdit, aimsedit.AimsEdit):
            return
        try:
            aimsEdit.save()
        except (IOError, OSError), e:
            QMessageBox.warning(self, "Aims Editor -- Save Error",
                    "Failed to save %s: %s" % (aimsEdit.filename, e))
        self.setActionsEnabled()

    def fileSaveAs(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None or not isinstance(aimsEdit, aimsedit.AimsEdit):
            return
        filename = QFileDialog.getSaveFileName(self,
                        "Aims Editor -- Save File As",
                        aimsEdit.filename, "Aims files (*.xml *.*)")
        if not filename.isEmpty():
            aimsEdit.filename = filename
            self.fileSave()
        self.setActionsEnabled()

    def fileExport2Pdf(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None or not isinstance(aimsEdit, aimsedit.AimsEdit):
            return
        filename = aimsEdit.filename
        if filename is None:
            return
        try:
            printer = QPrinter()
            printer.setOutputFormat(QPrinter.PdfFormat)
            filename = filename.replace(".xml", ".pdf")
            printer.setOutputFileName(filename)
            aimsEdit.export2Pdf(printer)
            
            QMessageBox.information(self, "Aims Editor -- PDF Export", "Export %s to %s successfuly completed!" % (aimsEdit.filename, filename))
        except (Exception), e:
            QMessageBox.warning(self, "Aims Editor -- PDF Export Error", "Failed to export to PDF %s: %s" % (aimsEdit.filename, e))
        self.setActionsEnabled()

    def fileSaveAll(self):
        errors = []
        for aimsEdit in self.mdi.windowList():
            if aimsEdit.isModified():
                try:
                    aimsEdit.save()
                except (IOError, OSError), e:
                    errors.append("%s: %s" % (aimsEdit.filename, e))
        if errors:
            QMessageBox.warning(self, "Aims Editor -- Save All Error",
                    "Failed to save\n%s" % "\n".join(errors))
        self.setActionsEnabled()

    def editCopy(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None or not isinstance(aimsEdit, aimsedit.AimsEdit):
            return
        aimsEdit.onCopy()
        self.setActionsEnabled()

    def editCut(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None or not isinstance(aimsEdit, aimsedit.AimsEdit):
            return
        aimsEdit.onCut()
        self.setActionsEnabled()


    def editPaste(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None or not isinstance(aimsEdit, aimsedit.AimsEdit):
            return
        aimsEdit.onPaste()
        self.setActionsEnabled()

    def setActionsEnabled(self):
        aimsEdit = self.mdi.activeWindow()
        if aimsEdit is None:
            self.editCopyAction.setEnabled(False)
            self.editCutAction.setEnabled(False)
            self.editPasteAction.setEnabled(False)

            self.fileSaveAction.setEnabled(False)
        else:
            self.editCopyAction.setEnabled(True)
            # Вырезать можно только тогда, когда можно удалять:
            self.editCutAction.setEnabled(aimsEdit.isDeletionAvalible())
            # Вставлять можно, если в принципе можно вставлять, и есть что вставить:
            self.editPasteAction.setEnabled(aimsEdit.isAdditionAvalible() and len(QApplication.clipboard().text()) > 0)
            
            self.fileSaveAction.setEnabled(aimsEdit.isModified())

    def windowRestoreAll(self):
        for aimsEdit in self.mdi.windowList():
            aimsEdit.showNormal()


    def windowMinimizeAll(self):
        for aimsEdit in self.mdi.windowList():
            aimsEdit.showMinimized()


    def updateWindowMenu(self):
        self.windowMenu.clear()
        self.addActions(self.windowMenu, (self.windowNextAction,
                self.windowPrevAction, self.windowCascadeAction,
                self.windowTileAction, self.windowRestoreAction,
                self.windowMinimizeAction,
                self.windowArrangeIconsAction, None,
                self.windowCloseAction))
        aimsEdits = self.mdi.windowList()
        if not aimsEdits:
            return
        self.windowMenu.addSeparator()
        i = 1
        menu = self.windowMenu
        for aimsEdit in aimsEdits:
            title = aimsEdit.windowTitle()
            if i == 10:
                self.windowMenu.addSeparator()
                menu = menu.addMenu("&More")
            accel = ""
            if i < 10:
                accel = "&%d " % i
            elif i < 36:
                accel = "&%c " % chr(i + ord("@") - 9)
            action = menu.addAction("%s%s" % (accel, title))
            self.connect(action, SIGNAL("triggered()"),
                         self.windowMapper, SLOT("map()"))
            self.windowMapper.setMapping(action, aimsEdit)
            i += 1


app = QApplication(sys.argv)
app.setWindowIcon(QIcon(":/icon.png"))
app.setApplicationName("Aims Editor")
form = MainWindow()
form.show()
app.exec_()